package com.petecat.interchan.sso.sysfun.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.mhuang.common.util.DataUtils;
import com.petecat.interchan.core.exception.BusinessException;
import com.petecat.interchan.core.service.impl.BaseServiceImpl;
import com.petecat.interchan.protocol.InsertInto;
import com.petecat.interchan.protocol.Result;
import com.petecat.interchan.protocol.data.Page;
import com.petecat.interchan.protocol.data.PageVO;
import com.petecat.interchan.protocol.sso.sysfun.SysFunAddDTO;
import com.petecat.interchan.protocol.sso.sysfun.SysFunDTO;
import com.petecat.interchan.protocol.sso.sysfun.SysFunModDTO;
import com.petecat.interchan.protocol.sso.sysfun.SysFunPageQueryDTO;
import com.petecat.interchan.protocol.sso.sysfun.SysFunQueryDTO;
import com.petecat.interchan.protocol.sso.sysfun.SysFunTreeQueryDTO;
import com.petecat.interchan.protocol.sso.sysfun.SysFunVO;
import com.petecat.interchan.redis.IdWorker;
import com.petecat.interchan.sso.sysfun.entity.SyChanmgfunm;
import com.petecat.interchan.sso.sysfun.mapper.SysFunMapper;
import com.petecat.interchan.sso.sysfun.service.ISysFunService;
import com.petecat.interchan.sso.sysrolefun.service.ISysRoleFunService;

/**
 * 
 * @ClassName: SysFunServiceImpl
 * @Description:系统功能权限服务
 * @author: 张小虎
 * @date: 2017年7月19日 上午10:10:04
 */
@Service("sysFunService")
@Transactional(readOnly = true)
public class SysFunServiceImpl extends BaseServiceImpl<SyChanmgfunm, String> implements ISysFunService {

	@Autowired
	private SysFunMapper sysFunMapper;

	@Autowired
	private Environment environment;

	@Autowired
	private ISysRoleFunService sysRoleFunService;

	public void setMapper(SysFunMapper sysFunMapper) {
		this.setBaseMapper(sysFunMapper);
	}

	/**
	 * <p>
	 * Title: saveFun
	 * </p>
	 * <p>
	 * Description:
	 * </p>
	 * 
	 * @param sysFunAddDTO
	 * @param userId
	 * @see com.petecat.interchan.sso.sysfun.service.ISysFunService#saveFun(com.petecat.interchan.protocol.sso.sysfun.SysFunAddDTO,
	 *      java.lang.String)
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public void saveFun(SysFunAddDTO sysFunAddDTO, String userId) {
		// 检查代号是否存在
		SyChanmgfunm fun = this.sysFunMapper.getById(sysFunAddDTO.getFunid());
		if (fun != null) {// 存在功能权限代码
			throw new BusinessException(Result.SYS_RESULT_FAILD, this.environment.getProperty("sysfunid_exists"));
		}
		fun = DataUtils.copyTo(sysFunAddDTO, SyChanmgfunm.class);
		if ("TOP".equals(fun.getFunid())) {
			throw new BusinessException(Result.SYS_RESULT_FAILD, this.environment.getProperty("sysfunid_is_error"));
		}
		fun.setOperateTime(new Date());
		fun.setOperateUser(userId);
		if (StringUtils.isNotBlank(fun.getParentid()) && !"TOP".equals(fun.getParentid())) {
			SyChanmgfunm parent = this.getById(fun.getParentid());
			if (parent == null) {
				throw new BusinessException(Result.SYS_RESULT_FAILD,
						this.environment.getProperty("sysfunparent_not_exists"));
			}
			fun.setLayid(parent.getLayid() + 1);
		} else {
			fun.setParentid("TOP");
			fun.setLayid(1);
		}
		this.sysFunMapper.save(fun);
		InsertInto<String> into = new InsertInto<>();
		into.setReqNo(new IdWorker().nextId()+"");
		into.setId(fun.getFunid());
		into.setStatus(InsertInto.ADD);
		into.setUserId(userId);
		this.sysFunMapper.insertInto(into);
	}

	/**
	 * <p>
	 * Title: saveFun
	 * </p>
	 * <p>
	 * Description:
	 * </p>
	 * 
	 * @param sysFunAddDTO
	 * @param userId
	 * @see com.petecat.interchan.sso.sysfun.service.ISysFunService#saveFun(com.petecat.interchan.protocol.sso.sysfun.SysFunAddDTO,
	 *      java.lang.String)
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public void updateFun(SysFunModDTO sysFunModDTO, String userId) {
		// 检查代号是否存在
		SyChanmgfunm fun = this.sysFunMapper.getById(sysFunModDTO.getFunid());
		if (fun == null) {// 存在不存在功能权限代码
			throw new BusinessException(Result.SYS_RESULT_FAILD, this.environment.getProperty("sysfun_not_exists"));
		}
		DataUtils.copyTo(sysFunModDTO, fun);
		fun.setOperateTime(new Date());
		fun.setOperateUser(userId);
		if (StringUtils.isNotBlank(sysFunModDTO.getParentid()) && !"TOP".equals(fun.getParentid())) {
			SyChanmgfunm parent = this.getById(sysFunModDTO.getParentid());
			if (parent == null) {
				throw new BusinessException(Result.SYS_RESULT_FAILD,
						this.environment.getProperty("sysfunparent_not_exists"));
			}
			fun.setLayid(parent.getLayid() + 1);
		} else {
			fun.setParentid("TOP");
			fun.setLayid(1);
		}
		this.sysFunMapper.updateById(fun);
		InsertInto<String> into = new InsertInto<>();
		into.setReqNo(new IdWorker().nextId()+"");
		into.setId(fun.getFunid());
		into.setStatus(InsertInto.UPDATE);
		into.setUserId(userId);
		this.sysFunMapper.insertInto(into);
	}

	/**
	 * <p>
	 * Title: queryFunByPage
	 * </p>
	 * <p>
	 * Description:
	 * </p>
	 * 
	 * @param dto
	 * @return
	 * @see com.petecat.interchan.sso.sysfun.service.ISysFunService#queryFunByPage(com.petecat.interchan.protocol.sso.sysfun.SysFunPageQueryDTO)
	 */
	@Override
	public PageVO<SysFunVO> queryFunByPage(SysFunPageQueryDTO dto) {
		Page<SyChanmgfunm> page = new Page<>();
		SyChanmgfunm funm = DataUtils.copyTo(dto, SyChanmgfunm.class);
		page.setRecord(funm);
		page.setRows(dto.getRows());
		page.setStart(dto.getStart() - 1);
		PageVO<SysFunVO> pageVo = new PageVO<>();
		List<SyChanmgfunm> sysFuns = sysFunMapper.page(page);
		pageVo.setResult(DataUtils.copyTo(sysFuns, SysFunVO.class));
		pageVo.setTotalSize(this.sysFunMapper.pageCount(page));
		return pageVo;
	}

	/**
	 * <p>
	 * Title: queryFun
	 * </p>
	 * <p>
	 * Description:
	 * </p>
	 * 
	 * @param funid
	 * @param nullException
	 *            是否抛出数据不存在异常
	 * @return SysFunQueryDTO
	 * @see com.petecat.interchan.sso.sysfun.service.ISysFunService#queryFun(funid,nullException)
	 */
	@Override
	public SysFunQueryDTO queryFun(String funid, boolean nullException) {
		SyChanmgfunm fun = sysFunMapper.getById(funid);
		SysFunQueryDTO dto = null;
		if (fun == null) {
			if (nullException) {
				throw new BusinessException(Result.SYS_RESULT_FAILD, this.environment.getProperty("sysfun_not_exists"));
			}
		} else {
			dto = new SysFunQueryDTO();
			if (StringUtils.isNotBlank(fun.getParentid())) {
				try {
					dto.setParentName(this.getById(fun.getParentid()).getFundesc());
				} catch (Exception e) {
				}
			}
			DataUtils.copyTo(fun, dto);
		}
		return dto;
	}

	/**
	 * <p>
	 * Title: deleteFun
	 * </p>
	 * <p>
	 * Description:
	 * </p>
	 * 
	 * @param funid
	 * @see com.petecat.interchan.sso.sysfun.service.ISysFunService#deleteFun(java.lang.String)
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public void deleteFun(String funid, String userId) {
		List<SyChanmgfunm> childFuns = this.sysFunMapper.queryFunByParent(funid);
		List<String> ids = new ArrayList<>();
		ids.add(funid);
		List<String> queryIds = new ArrayList<>();
		while (!CollectionUtils.isEmpty(childFuns)) {
			childFuns.parallelStream().forEach((data) -> {
				if (!ids.contains(data.getFunid())) {
					ids.add(data.getFunid());
					queryIds.add(data.getFunid());
				}
			});
			childFuns = null;
			if (!CollectionUtils.isEmpty(queryIds)) {
				childFuns = this.sysFunMapper.queryFunByParents(queryIds);
			}
			queryIds.clear();
		}
		InsertInto<List<String>> into = new InsertInto<>();
		into.setReqNo(new IdWorker().nextId()+"");
		into.setId(ids);
		into.setStatus(InsertInto.DELETE);
		into.setUserId(userId);
		into.setOpDate(new Date());
		this.sysFunMapper.insertIntos(into);
		this.sysFunMapper.deleteFunByIds(ids);
		this.sysRoleFunService.deleteRoleFunByFuns(ids, userId);
	}

	/**
	 * <p>
	 * Title: queryFunTree
	 * </p>
	 * <p>
	 * Description:
	 * </p>
	 * 
	 * @param dto
	 * @return
	 * @see com.petecat.interchan.sso.sysfun.service.ISysFunService#queryFunTree(com.petecat.interchan.protocol.sso.sysfun.SysFunQueryDTO)
	 */
	@Override
	public List<SysFunVO> queryFunTree(SysFunTreeQueryDTO dto) {
		SyChanmgfunm funm = DataUtils.copyTo(dto, SyChanmgfunm.class);
		List<SysFunDTO> funs = this.sysFunMapper.queryFunTree(funm);
		return DataUtils.copyTo(funs, SysFunVO.class);
	}

}
